package utils
{
	import flash.geom.Point;
	
	import objects.SimbolInfo;

	public class RecognizeUtils
	{
		private const INTERLIEVE_GRANULARITY:Number = 64.0;
		
		public function get symbolsCount():uint{return data.length;}
		public function symbolAt(pos:int):String
		{
			return String.fromCharCode(data[pos].code);
		}
		public function pointsAt(pos:int):Vector.<Point>
		{
			return data[pos].points;
		}
		public function NormalizeSymbols(a:Vector.<SimbolInfo>):Vector.<SimbolInfo>
		{
			var ret:Vector.<SimbolInfo> = new Vector.<SimbolInfo>() 
			for each (var s:SimbolInfo in a) 
			{
				ret.push(NormalizePoints(s.points));
			}
			return ret;
		}
		public function NormalizePoints (s:Vector.<Point>):Vector.<Point>
		{
			var srcLen:int = int(s.length);
			var letterNorm:Vector.<Point> = new Vector.<Point>(srcLen)
			var ret:Vector.<Point> = new Vector.<Point>(INTERLIEVE_GRANULARITY);
			var lengths:Vector.<Number> = new Vector.<Number>(srcLen);

			
			var max:Point = new Point(int.MIN_VALUE, int.MIN_VALUE);
			var min:Point = new Point(int.MAX_VALUE, int.MAX_VALUE);
			for each (var p:Point in s) 
			{
				max.x = Math.max(max.x, p.x);
				max.y = Math.max(max.y, p.y);
				min.x = Math.min(min.x, p.x);
				min.y = Math.min(min.y, p.y);
			}
			var dx:Number = max.x - min.x;
			var dy:Number = max.y - min.y;
			var letter:int = 0;
			if (dx + dy < 6.0) 
			{
				letter = '.'.charCodeAt();
			} else if (max.y == min.y || dx / dy > 6.0) 
			{
				letter = '-'.charCodeAt();
			} else if (max.x == min.x || dy / dx > 6.0) 
			{
				letter = '|'.charCodeAt();
			}
			
			
			for(var n:int=0; n < srcLen; n++) 
			{
				p = s[n]
				var np:Point = new Point();
				if (letter == '|'.charCodeAt() || letter == '.'.charCodeAt()) {
					np.x = 0.0;
				}else 
				{
					np.x = ((p.x) - min.x) / dx;
				}
				if (letter == '-'.charCodeAt() || letter == '.'.charCodeAt()) {
					np.y = 0.0;
				}else 
				{
					np.y = ((p.y) - min.y) / dy;
				}
				letterNorm[n] = np;
			}
			
			lengths[0] = 0.0;
			for (var i:int = 1; i < srcLen; i++) 
			{
				lengths[i] = lengths[i - 1] + letterNorm[i].subtract(letterNorm[i - 1]).length;
				/*
				lengths[i] = lengths[i - 1] + Math.sqrt((letterNorm[i].x - letterNorm[i - 1].x) * (letterNorm[i].x - letterNorm[i - 1].x)
					+ (letterNorm[i].y - letterNorm[i - 1].y) * (letterNorm[i].y - letterNorm[i - 1].y));
				
				*/
			}
			
			var index:int;
			var totalLength:Number = lengths[srcLen - 1];
			for (var subDivisionIndex:Number = 0.0; subDivisionIndex < INTERLIEVE_GRANULARITY; subDivisionIndex++) 
			{
				var percentage:Number = ( subDivisionIndex / (INTERLIEVE_GRANULARITY - 1.0));
				var percentageLength:Number = totalLength * percentage;
				
				for (index = 1; lengths[index] < percentageLength; )
					index++;
				if (index > srcLen - 1) 
					index = srcLen - 1;
				var dlen:Number = lengths[index] - lengths[index - 1];
				if (dlen == 0.0) 
				{
					ret[subDivisionIndex] = new Point(letterNorm[index].x, letterNorm[index].y);
				} else 
				{
					var f3:Number = (lengths[index] - percentageLength) / dlen;
					ret[subDivisionIndex] = new Point(
						(f3 * letterNorm[index - 1].x) + ((1.0 - f3) * letterNorm[index].x),
						(f3 * letterNorm[index - 1].y) + ((1.0 - f3) * letterNorm[index].y)
						);
				}
			}
			return ret;
		}
		public function recognize(path:Vector.<Point>):int
		{
			var lastDistance:Number = Number.MAX_VALUE;
			var ret:int = 0;
			for each(var si:SimbolInfo in data)
			{
				var npath:Vector.<Point> = NormalizePoints(path);
				var nsrc:Vector.<Point> = NormalizePoints(si.points);
				var curDistance:Number = avgDistance(nsrc, npath);
				if(curDistance < lastDistance)
				{
					lastDistance = curDistance;
					ret = si.code;
				}
					
			}
			return ret;
		}
		
		private function avgDistance(p0:Vector.<Point>, p1:Vector.<Point>):Number
		{
			var ret:Number = 0;
			for(var i:int=0; i<p0.length; i++)
			{
				ret = ret + p0[i].subtract(p1[i]).length;
			}
			return ret;
		}
		
		private  var data:Vector.<SimbolInfo> = new <SimbolInfo>
			[
				new SimbolInfo('A', new <Point>[new Point(0, 10), new Point(5, 0), new Point(10, 10)]),
				new SimbolInfo('B', new <Point>[new Point(0, 0), new Point(10, 3), new Point(0, 5), new Point(10, 8), new Point(0, 10)]),
				new SimbolInfo('B', new <Point>[new Point(0, 0), new Point(0, 10), new Point(0, 7), new Point(10, 7), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('B', new <Point>[new Point(0, 10), new Point(0, 0), new Point(10, 0), new Point(10, 5), new Point(0, 5), new Point(10, 5), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('B', new <Point>[new Point(0, 0), new Point(10, 0), new Point(10, 5), new Point(0, 5), new Point(10, 5), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('C', new <Point>[new Point(10, 0), new Point(0, 0), new Point(0, 10), new Point(10, 10)]),
				new SimbolInfo('C', new <Point>[new Point(5, 0), new Point(0, 0), new Point(0, 10), new Point(10, 10)]),
				new SimbolInfo('D', new <Point>[new Point(0, 10), new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('D', new <Point>[new Point(0, 10), new Point(10, 0), new Point(0, 0), new Point(10, 10)]),
				new SimbolInfo('D', new <Point>[new Point(0, 0), new Point(0, 10), new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('D', new <Point>[new Point(10, 10), new Point(0, 0), new Point(10, 0), new Point(0, 10)]),
				new SimbolInfo('E', new <Point>[new Point(10, 0), new Point(0, 3), new Point(10, 5), new Point(0, 8), new Point(10, 10)]),
				new SimbolInfo('E', new <Point>[new Point(0, 10), new Point(7, 5), new Point(6, 2), new Point(3, 3), new Point(3, 6), new Point(10, 0)]),
				new SimbolInfo('E', new <Point>[new Point(0, 5), new Point(10, 5), new Point(10, 0), new Point(0, 0), new Point(0, 10), new Point(10, 10)]),
				new SimbolInfo('F', new <Point>[new Point(10, 0), new Point(0, 0), new Point(0, 10)]),
				new SimbolInfo('F', new <Point>[new Point(10, 0), new Point(0, 3), new Point(0, 10)]),
				new SimbolInfo('G', new <Point>[new Point(10, 0), new Point(0, 0), new Point(0, 10), new Point(10, 10), new Point(10, 5), new Point(0, 5)]),
				new SimbolInfo('G', new <Point>[new Point(10, 0), new Point(3, 0), new Point(3, 10), new Point(10, 10), new Point(10, 5), new Point(0, 5)]),
				new SimbolInfo('H', new <Point>[new Point(0, 0), new Point(0, 10), new Point(7, 0), new Point(10, 10)]),
				new SimbolInfo('H', new <Point>[new Point(0, 0), new Point(0, 10), new Point(5, 5), new Point(10, 10)]),
				new SimbolInfo('I', new <Point>[new Point(5, 0), new Point(5, 5)]),
				new SimbolInfo('J', new <Point>[new Point(10, 0), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('J', new <Point>[new Point(10, 0), new Point(10, 7), new Point(5, 10), new Point(0, 8), new Point(0, 6)]),
				new SimbolInfo('K', new <Point>[new Point(10, 0), new Point(0, 10), new Point(0, 0), new Point(10, 10)]),
				new SimbolInfo('K', new <Point>[new Point(10, 0), new Point(6, 3), new Point(0, 5), new Point(5, 7), new Point(10, 10)]),
				new SimbolInfo('L', new <Point>[new Point(0, 0), new Point(0, 10), new Point(10, 10)]),
				new SimbolInfo('M', new <Point>[new Point(0, 10), new Point(0, 0), new Point(5, 10), new Point(10, 0), new Point(10, 10)]),
				new SimbolInfo('M', new <Point>[new Point(0, 10), new Point(3, 0), new Point(5, 10), new Point(8, 0), new Point(10, 10)]),
				new SimbolInfo('N', new <Point>[new Point(0, 10), new Point(0, 0), new Point(10, 10), new Point(10, 0)]),
				new SimbolInfo('N', new <Point>[new Point(0, 10), new Point(3, 0), new Point(7, 10), new Point(10, 0)]),
				new SimbolInfo('O', new <Point>[new Point(5, 0), new Point(0, 2), new Point(0, 8), new Point(5, 10), new Point(10, 8), new Point(10, 2), new Point(5, 0)]),
				new SimbolInfo('O', new <Point>[new Point(0, 0), new Point(0, 10), new Point(10, 10), new Point(10, 0), new Point(0, 0)]),
				new SimbolInfo('P', new <Point>[new Point(0, 10), new Point(0, 0), new Point(10, 0), new Point(10, 5), new Point(0, 5)]),
				new SimbolInfo('Q', new <Point>[new Point(5, 0), new Point(0, 2), new Point(0, 7), new Point(5, 10), new Point(10, 7), new Point(10, 3), new Point(5, 0), new Point(5, 1), new Point(10, 0)]),
				new SimbolInfo('Q', new <Point>[new Point(0, 0), new Point(0, 10), new Point(10, 10), new Point(10, 0), new Point(0, 0), new Point(10, 0)]),
				new SimbolInfo('R', new <Point>[new Point(0, 10), new Point(0, 0), new Point(10, 0), new Point(10, 4), new Point(1, 5), new Point(10, 10)]),
				new SimbolInfo('R', new <Point>[new Point(0, 10), new Point(0, 0), new Point(10, 3), new Point(1, 5), new Point(10, 10)]),
				new SimbolInfo('S', new <Point>[new Point(10, 0), new Point(0, 0), new Point(0, 5), new Point(10, 5), new Point(10, 10), new Point(0, 10)]),
				new SimbolInfo('S', new <Point>[new Point(10, 0), new Point(0, 3), new Point(10, 7), new Point(0, 10)]),
				new SimbolInfo('T', new <Point>[new Point(0, 0), new Point(10, 0), new Point(10, 10)]),
				new SimbolInfo('U', new <Point>[new Point(0, 0), new Point(5, 10), new Point(10, 0)]),
				new SimbolInfo('V', new <Point>[new Point(10, 0), new Point(5, 10), new Point(0, 0)]),
				new SimbolInfo('W', new <Point>[new Point(0, 0), new Point(3, 10), new Point(5, 0), new Point(8, 10), new Point(10, 0)]),
				new SimbolInfo('W', new <Point>[new Point(0, 0), new Point(3, 10), new Point(5, 5), new Point(8, 10), new Point(10, 0)]),
				new SimbolInfo('X', new <Point>[new Point(0, 0), new Point(10, 10), new Point(10, 0), new Point(0, 10)]),
				new SimbolInfo('X', new <Point>[new Point(0, 0), new Point(5, 10), new Point(8, 10), new Point(10, 5), new Point(8, 0), new Point(5, 0), new Point(0, 10)]),
				new SimbolInfo('Y', new <Point>[new Point(0, 0), new Point(10, 10), new Point(0, 10), new Point(10, 0)]),
				new SimbolInfo('Y', new <Point>[new Point(0, 0), new Point(10, 6), new Point(8, 10), new Point(2, 10), new Point(0, 6), new Point(10, 0)]),
				new SimbolInfo('Y', new <Point>[new Point(0, 0), new Point(5, 3), new Point(10, 0), new Point(9, 6), new Point(4, 10), new Point(0, 8), new Point(1, 6), new Point(10, 4)]),
				new SimbolInfo('Z', new <Point>[new Point(0, 0), new Point(10, 0), new Point(0, 10), new Point(10, 10)]),
				new SimbolInfo('Z', new <Point>[new Point(0, 0), new Point(10, 3), new Point(0, 7), new Point(10, 10)])
				
			];
		
	}
}